package fsouza

import (
	"errors"
	"fmt"
	corev1 "gluenet/internal/agent/api/core/v1"
	"strings"

	docker "github.com/fsouza/go-dockerclient"
)

const (
	DEFAULT_TIME_OUT = 10
)

type FsouzaDockerDriver struct {
	cli *docker.Client
}

func NewDriver(url string) (*FsouzaDockerDriver, error) {
	var (
		cli *docker.Client
		err error
	)

	if url == `` {
		cli, err = docker.NewClientFromEnv()
	} else {
		cli, err = docker.NewClient(url)
	}

	if err != nil {
		return nil, err
	}

	return &FsouzaDockerDriver{
		cli: cli,
	}, nil
}

func (r *FsouzaDockerDriver) Create(container *corev1.Container) (cd corev1.ContaienrDetial, err error) {
	cd = corev1.ContaienrDetial{}
	ct, err := r.cli.CreateContainer(docker.CreateContainerOptions{
		Name:             container.Name,
		Config:           container.Config,
		HostConfig:       container.HostConfig,
		NetworkingConfig: container.NetworkingConfig,
	})

	if err != nil {
		return
	}

	if err = r.cli.StartContainer(ct.ID, ct.HostConfig); err != nil {
		return
	}

	cd.Container = ct
	return
}

func (r *FsouzaDockerDriver) Get(id string) (cd corev1.ContaienrDetial, err error) {
	cd = corev1.ContaienrDetial{}
	ct, err := r.cli.InspectContainerWithOptions(docker.InspectContainerOptions{ID: id})
	if err != nil {
		return
	}

	cd.Container = ct
	return
}

func (r *FsouzaDockerDriver) Delete(id string) (err error) {
	var errStr []string

	if err = r.cli.StopContainer(id, DEFAULT_TIME_OUT); err != nil {
		errStr = append(errStr, fmt.Sprint("stop container err: ", err))
	}
	if err = r.cli.RemoveContainer(docker.RemoveContainerOptions{ID: id}); err != nil {
		errStr = append(errStr, fmt.Sprint("delete container err: ", err))
	}

	if err != nil {
		return errors.New(strings.Join(errStr, "\n"))
	}

	return nil
}

func (r *FsouzaDockerDriver) Update(id string, option corev1.ContainerOptions) error {
	opt := docker.UpdateContainerOptions{}
	opt.BlkioWeight = option.BlkioWeight
	opt.CpusetCpus = option.CpusetCpus
	opt.CPUPeriod = option.CPUPeriod
	opt.CPUShares = option.CPUShares

	return r.cli.UpdateContainer(id, opt)
}

// pull image like: 152.136.134.100:10048/jaeger-collector-glunet
func (r *FsouzaDockerDriver) Pull(image string) error {
	return r.cli.PullImage(docker.PullImageOptions{
		Repository: image,
	}, docker.AuthConfiguration{})
}

func (r *FsouzaDockerDriver) Stop(containerId string) error {

	return r.cli.StopContainer(containerId, DEFAULT_TIME_OUT)
}

func (r *FsouzaDockerDriver) Resume(containerId string) error {

	return r.cli.StartContainer(containerId, &docker.HostConfig{})
}

func (r *FsouzaDockerDriver) ReStart(containerId string) error {

	return r.cli.RestartContainer(containerId, DEFAULT_TIME_OUT)
}

func (r *FsouzaDockerDriver) Remove(containerId string) error {

	return r.cli.RemoveContainer(docker.RemoveContainerOptions{
		ID: containerId,
	})
}

func (r *FsouzaDockerDriver) Exec(containerId string, cmd []string) error {
	_, err := r.cli.CreateExec(docker.CreateExecOptions{Container: containerId, Cmd: cmd})
	return err
}

func (r *FsouzaDockerDriver) Close() error {
	return nil
}
